<!DOCTYPE HTML>
<html>
<head>
<title>JavaScript Test ALL</title>
</head>
<body>
<h1>JavaScript Test All Examples</h1>
<script type="text/javascript"src=./rand.js></script>
<script type="text/javascript"src=./rom_curve.js></script>
<script type="text/javascript"src=./rom_field.js></script>
<script type="text/javascript"src=./uint64.js></script>
<script type="text/javascript"src=./aes.js></script>
<script type="text/javascript"src=./big.js></script>
<script type="text/javascript"src=./gcm.js></script>
<script type="text/javascript"src=./hash256.js></script>
<script type="text/javascript"src=./hash384.js></script>
<script type="text/javascript"src=./hash512.js></script>
<script type="text/javascript"src=./sha3.js></script>
<script type="text/javascript"src=./nhs.js></script>
<script type="text/javascript"src=./fp.js></script>
<script type="text/javascript"src=./fp2.js></script>
<script type="text/javascript"src=./fp4.js></script>
<script type="text/javascript"src=./fp12.js></script>
<script type="text/javascript"src=./ff.js></script>
<script type="text/javascript"src=./rsa.js></script>
<script type="text/javascript"src=./ecp.js></script>
<script type="text/javascript"src=./ecp2.js></script>
<script type="text/javascript"src=./ecdh.js></script>
<script type="text/javascript"src=./pair.js></script>
<script type="text/javascript"src=./mpin.js></script>
<script type="text/javascript"src=./bls.js></script>
<script type="text/javascript"src=./ctx.js></script>

<script type="text/javascript"src=./fp8.js></script>
<script type="text/javascript"src=./fp16.js></script>
<script type="text/javascript"src=./fp24.js></script>
<script type="text/javascript"src=./fp48.js></script>
<script type="text/javascript"src=./ecp4.js></script>
<script type="text/javascript"src=./ecp8.js></script>
<script type="text/javascript"src=./pair192.js></script>
<script type="text/javascript"src=./pair256.js></script>
<script type="text/javascript"src=./mpin192.js></script>
<script type="text/javascript"src=./mpin256.js></script>
<script type="text/javascript"src=./bls192.js></script>
<script type="text/javascript"src=./bls256.js></script>

<p><a id="myLink1" href="#" onclick="location.reload(false);ed25519();">ED25519 255-bit Edwards Elliptic Curve ECDH/ECIES/ECDSA</a></p>
<p><a id="myLink2" href="#" onclick="location.reload(false);nist256();">NIST256 256-bit Weierstrass Elliptic Curve ECDH/ECIES/ECDSA</a></p>
<p><a id="myLink3" href="#" onclick="location.reload(false);goldilocks();">GOLDILOCKS 448-bit Edwards Elliptic Curve ECDH/ECIES/ECDSA</a></p>
<p><a id="myLink4" href="#" onclick="location.reload(false);bn254();">BN254 254-bit k=12 Pairing-Friendly BN Curve MPIN</a></p>
<p><a id="myLink5" href="#" onclick="location.reload(false);bls383();">BLS383 383-bit k=12 Pairing-Friendly BLS Curve MPIN</a></p>
<p><a id="myLink6" href="#" onclick="location.reload(false);bls24();">BLS24 479-bit k=24 Pairing-Friendly BLS Curve MPIN</a></p>
<p><a id="myLink7" href="#" onclick="location.reload(false);bls48();">BLS48 556-bit k=48 Pairing-Friendly BLS Curve MPIN</a></p>
<p><a id="myLink8" href="#" onclick="location.reload(false);rsa2048();">RSA2048 2048-bit RSA Key generation/Encryption/Decryption</a></p>


<script>

/* Test ECC */
/* test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */

// ED25519 context
function ed25519() {
	var ctx = new CTX('ED25519');

	mywindow=window.open();

	mywindow.document.write("<br> ED25519 Curve "+  "<br>");

	var i,j=0,res;
	var result;
	var pp="M0ng00se";

	var EGS=ctx.ECDH.EGS;
	var EFS=ctx.ECDH.EFS;
	var EAS=ctx.ECP.AESKEY;
	var sha=ctx.ECP.HASH_TYPE;

	var S1=[];
	var W0=[];
	var W1=[];
	var Z0=[];
	var Z1=[];
	var RAW=[];
	var SALT=[];
	var P1=[];
	var P2=[];
	var V=[];
	var M=[];
	var T=new Array(12);  // must specify required length
	var CS=[];
	var DS=[];

	var rng=new ctx.RAND();

	rng.clean();
	for (i=0;i<100;i++) RAW[i]=i;

	rng.seed(100,RAW);

	for (i=0;i<8;i++) SALT[i]=(i+1);  // set Salt

	mywindow.document.write("Alice's Passphrase= " + pp + "<br>");

	var PW=ctx.ECDH.asciitobytes(pp);
/* private key S0 of size EGS bytes derived from Password and Salt */
	var S0=ctx.ECDH.PBKDF2(sha,PW,SALT,1000,EGS);

	mywindow.document.write("Alice's private key= 0x"+ctx.ECDH.bytestostring(S0)+ "<br>");
/* Generate Key pair S/W */
	ctx.ECDH.KEY_PAIR_GENERATE(null,S0,W0); 

	mywindow.document.write("Alice's public key= 0x"+ctx.ECDH.bytestostring(W0)+ "<br>");

	res=ctx.ECDH.PUBLIC_KEY_VALIDATE(W0);
	if (res!=0)
		alert("ECP Public Key is invalid!");
/* Random private key for other party */
	ctx.ECDH.KEY_PAIR_GENERATE(rng,S1,W1);

	mywindow.document.write("Servers private key= 0x"+ctx.ECDH.bytestostring(S1)+ "<br>");
	mywindow.document.write("Servers public key= 0x"+ctx.ECDH.bytestostring(W1)+ "<br>");

	res=ctx.ECDH.PUBLIC_KEY_VALIDATE(W1);
	if (res!=0)
		alert("ECP Public Key is invalid!");
			

/* Calculate common key using DH - IEEE 1363 method */

	ctx.ECDH.ECPSVDP_DH(S0,W1,Z0);
	ctx.ECDH.ECPSVDP_DH(S1,W0,Z1);

	var same=true;
	for (i=0;i<ctx.ECDH.EFS;i++)
		if (Z0[i]!=Z1[i]) same=false;

	if (!same)
		alert("*** ECPSVDP-DH Failed");

	var KEY=ctx.ECDH.KDF2(sha,Z0,null,ctx.ECP.AESKEY);

	mywindow.document.write("Alice's ECDH Key=  0x"+ctx.ECDH.bytestostring(KEY)+ "<br>");
	mywindow.document.write("Servers ECDH Key=  0x"+ctx.ECDH.bytestostring(KEY)+ "<br>");

	if (ctx.ECP.CURVETYPE!=ctx.ECP.MONTGOMERY)
	{
		mywindow.document.write("Testing ECIES"+ "<br>");

		P1[0]=0x0; P1[1]=0x1; P1[2]=0x2; 
		P2[0]=0x0; P2[1]=0x1; P2[2]=0x2; P2[3]=0x3; 

		for (i=0;i<=16;i++) M[i]=i; 

		var C=ctx.ECDH.ECIES_ENCRYPT(sha,P1,P2,rng,W1,M,V,T);

		mywindow.document.write("Ciphertext= "+ "<br>");
		mywindow.document.write("V= 0x"+ctx.ECDH.bytestostring(V)+ "<br>");
		mywindow.document.write("C= 0x"+ctx.ECDH.bytestostring(C)+ "<br>");
		mywindow.document.write("T= 0x"+ctx.ECDH.bytestostring(T)+ "<br>");


		M=ctx.ECDH.ECIES_DECRYPT(sha,P1,P2,V,C,T,S1);
		if (M.length==0)
			alert("*** ECIES Decryption Failed ");
		else mywindow.document.write("Decryption succeeded"+ "<br>");

		mywindow.document.write("Message is 0x"+ctx.ECDH.bytestostring(M)+ "<br>");

		mywindow.document.write("Testing ECDSA"+ "<br>");

		if (ctx.ECDH.ECPSP_DSA(sha,rng,S0,M,CS,DS)!=0)
			alert("***ECDSA Signature Failed");
		
		mywindow.document.write("Signature= "+ "<br>");
		mywindow.document.write("C= 0x"+ctx.ECDH.bytestostring(CS)+ "<br>");
		mywindow.document.write("D= 0x"+ctx.ECDH.bytestostring(DS)+ "<br>");

		if (ctx.ECDH.ECPVP_DSA(sha,W0,M,CS,DS)!=0)
			alert("***ECDSA Verification Failed");
		else mywindow.document.write("ECDSA Signature/Verification succeeded "+  "<br>");
	}

}
// NIST256 context

function nist256() {
	var ctx = new CTX('NIST256');
	mywindow=window.open();

	mywindow.document.write("<br> NIST256 Curve "+  "<br>");
	var i,j=0,res;
	var result;
	var pp="M0ng00se";

	var EGS=ctx.ECDH.EGS;
	var EFS=ctx.ECDH.EFS;
	var EAS=ctx.ECP.AESKEY;
	var sha=ctx.ECP.HASH_TYPE;

	var S1=[];
	var W0=[];
	var W1=[];
	var Z0=[];
	var Z1=[];
	var RAW=[];
	var SALT=[];
	var P1=[];
	var P2=[];
	var V=[];
	var M=[];
	var T=new Array(12);  // must specify required length
	var CS=[];
	var DS=[];

	var rng=new ctx.RAND();

	rng.clean();
	for (i=0;i<100;i++) RAW[i]=i;

	rng.seed(100,RAW);


	for (i=0;i<8;i++) SALT[i]=(i+1);  // set Salt

	mywindow.document.write("Alice's Passphrase= " + pp + "<br>");

	var PW=ctx.ECDH.asciitobytes(pp);
/* private key S0 of size EGS bytes derived from Password and Salt */
	var S0=ctx.ECDH.PBKDF2(sha,PW,SALT,1000,EGS);

	mywindow.document.write("Alice's private key= 0x"+ctx.ECDH.bytestostring(S0)+ "<br>");
/* Generate Key pair S/W */
	ctx.ECDH.KEY_PAIR_GENERATE(null,S0,W0); 

	mywindow.document.write("Alice's public key= 0x"+ctx.ECDH.bytestostring(W0)+ "<br>");

	res=ctx.ECDH.PUBLIC_KEY_VALIDATE(W0);
	if (res!=0)
		alert("ECP Public Key is invalid!");
/* Random private key for other party */
	ctx.ECDH.KEY_PAIR_GENERATE(rng,S1,W1);

	mywindow.document.write("Servers private key= 0x"+ctx.ECDH.bytestostring(S1)+ "<br>");
	mywindow.document.write("Servers public key= 0x"+ctx.ECDH.bytestostring(W1)+ "<br>");

	res=ctx.ECDH.PUBLIC_KEY_VALIDATE(W1);
	if (res!=0)
		alert("ECP Public Key is invalid!");
			

/* Calculate common key using DH - IEEE 1363 method */

	ctx.ECDH.ECPSVDP_DH(S0,W1,Z0);
	ctx.ECDH.ECPSVDP_DH(S1,W0,Z1);

	var same=true;
	for (i=0;i<ctx.ECDH.EFS;i++)
		if (Z0[i]!=Z1[i]) same=false;

	if (!same)
		alert("*** ECPSVDP-DH Failed");

	var KEY=ctx.ECDH.KDF2(sha,Z0,null,ctx.ECP.AESKEY);

	mywindow.document.write("Alice's ECDH Key=  0x"+ctx.ECDH.bytestostring(KEY)+ "<br>");
	mywindow.document.write("Servers ECDH Key=  0x"+ctx.ECDH.bytestostring(KEY)+ "<br>");

	if (ctx.ECP.CURVETYPE!=ctx.ECP.MONTGOMERY)
	{
		mywindow.document.write("Testing ECIES"+ "<br>");

		P1[0]=0x0; P1[1]=0x1; P1[2]=0x2; 
		P2[0]=0x0; P2[1]=0x1; P2[2]=0x2; P2[3]=0x3; 

		for (i=0;i<=16;i++) M[i]=i; 

		var C=ctx.ECDH.ECIES_ENCRYPT(sha,P1,P2,rng,W1,M,V,T);

		mywindow.document.write("Ciphertext= "+ "<br>");
		mywindow.document.write("V= 0x"+ctx.ECDH.bytestostring(V)+ "<br>");
		mywindow.document.write("C= 0x"+ctx.ECDH.bytestostring(C)+ "<br>");
		mywindow.document.write("T= 0x"+ctx.ECDH.bytestostring(T)+ "<br>");


		M=ctx.ECDH.ECIES_DECRYPT(sha,P1,P2,V,C,T,S1);
		if (M.length==0)
			alert("*** ECIES Decryption Failed ");
		else mywindow.document.write("Decryption succeeded"+ "<br>");

		mywindow.document.write("Message is 0x"+ctx.ECDH.bytestostring(M)+ "<br>");

		mywindow.document.write("Testing ECDSA"+ "<br>");

		if (ctx.ECDH.ECPSP_DSA(sha,rng,S0,M,CS,DS)!=0)
			alert("***ECDSA Signature Failed");
		
		mywindow.document.write("Signature= "+ "<br>");
		mywindow.document.write("C= 0x"+ctx.ECDH.bytestostring(CS)+ "<br>");
		mywindow.document.write("D= 0x"+ctx.ECDH.bytestostring(DS)+ "<br>");

		if (ctx.ECDH.ECPVP_DSA(sha,W0,M,CS,DS)!=0)
			alert("***ECDSA Verification Failed");
		else mywindow.document.write("ECDSA Signature/Verification succeeded "+  "<br>");
	}

}


// GOLDILOCKS context
function goldilocks() {
	var ctx = new CTX('GOLDILOCKS');
	mywindow=window.open();

	mywindow.document.write("<br> GOLDILOCKS Curve "+  "<br>");

	var i,j=0,res;
	var result;
	var pp="M0ng00se";

	var EGS=ctx.ECDH.EGS;
	var EFS=ctx.ECDH.EFS;
	var EAS=ctx.ECP.AESKEY;
	var sha=ctx.ECP.HASH_TYPE;

	var S1=[];
	var W0=[];
	var W1=[];
	var Z0=[];
	var Z1=[];
	
	var SALT=[];
	var P1=[];
	var P2=[];
	var V=[];
	var M=[];
	var T=new Array(12);  // must specify required length
	var CS=[];
	var DS=[];

	var RAW=[];
	var rng=new ctx.RAND();

	rng.clean();
	for (i=0;i<100;i++) RAW[i]=i;

	rng.seed(100,RAW);


	for (i=0;i<8;i++) SALT[i]=(i+1);  // set Salt

	mywindow.document.write("Alice's Passphrase= " + pp + "<br>");

	var PW=ctx.ECDH.asciitobytes(pp);
/* private key S0 of size EGS bytes derived from Password and Salt */
	var S0=ctx.ECDH.PBKDF2(sha,PW,SALT,1000,EGS);

	mywindow.document.write("Alice's private key= 0x"+ctx.ECDH.bytestostring(S0)+ "<br>");
/* Generate Key pair S/W */
	ctx.ECDH.KEY_PAIR_GENERATE(null,S0,W0); 

	mywindow.document.write("Alice's public key= 0x"+ctx.ECDH.bytestostring(W0)+ "<br>");

	res=ctx.ECDH.PUBLIC_KEY_VALIDATE(W0);
	if (res!=0)
		alert("ECP Public Key is invalid!");
/* Random private key for other party */
	ctx.ECDH.KEY_PAIR_GENERATE(rng,S1,W1);

	mywindow.document.write("Servers private key= 0x"+ctx.ECDH.bytestostring(S1)+ "<br>");
	mywindow.document.write("Servers public key= 0x"+ctx.ECDH.bytestostring(W1)+ "<br>");

	res=ctx.ECDH.PUBLIC_KEY_VALIDATE(W1);
	if (res!=0)
		alert("ECP Public Key is invalid!");
			

/* Calculate common key using DH - IEEE 1363 method */

	ctx.ECDH.ECPSVDP_DH(S0,W1,Z0);
	ctx.ECDH.ECPSVDP_DH(S1,W0,Z1);

	var same=true;
	for (i=0;i<ctx.ECDH.EFS;i++)
		if (Z0[i]!=Z1[i]) same=false;

	if (!same)
		alert("*** ECPSVDP-DH Failed");

	var KEY=ctx.ECDH.KDF2(sha,Z0,null,ctx.ECP.AESKEY);

	mywindow.document.write("Alice's ECDH Key=  0x"+ctx.ECDH.bytestostring(KEY)+ "<br>");
	mywindow.document.write("Servers ECDH Key=  0x"+ctx.ECDH.bytestostring(KEY)+ "<br>");

	if (ctx.ECP.CURVETYPE!=ctx.ECP.MONTGOMERY)
	{
		mywindow.document.write("Testing ECIES"+ "<br>");

		P1[0]=0x0; P1[1]=0x1; P1[2]=0x2; 
		P2[0]=0x0; P2[1]=0x1; P2[2]=0x2; P2[3]=0x3; 

		for (i=0;i<=16;i++) M[i]=i; 

		var C=ctx.ECDH.ECIES_ENCRYPT(sha,P1,P2,rng,W1,M,V,T);

		mywindow.document.write("Ciphertext= "+ "<br>");
		mywindow.document.write("V= 0x"+ctx.ECDH.bytestostring(V)+ "<br>");
		mywindow.document.write("C= 0x"+ctx.ECDH.bytestostring(C)+ "<br>");
		mywindow.document.write("T= 0x"+ctx.ECDH.bytestostring(T)+ "<br>");


		M=ctx.ECDH.ECIES_DECRYPT(sha,P1,P2,V,C,T,S1);
		if (M.length==0)
			alert("*** ECIES Decryption Failed ");
		else mywindow.document.write("Decryption succeeded"+ "<br>");

		mywindow.document.write("Message is 0x"+ctx.ECDH.bytestostring(M)+ "<br>");

		mywindow.document.write("Testing ECDSA"+ "<br>");

		if (ctx.ECDH.ECPSP_DSA(sha,rng,S0,M,CS,DS)!=0)
			alert("***ECDSA Signature Failed");
		
		mywindow.document.write("Signature= "+ "<br>");
		mywindow.document.write("C= 0x"+ctx.ECDH.bytestostring(CS)+ "<br>");
		mywindow.document.write("D= 0x"+ctx.ECDH.bytestostring(DS)+ "<br>");

		if (ctx.ECDH.ECPVP_DSA(sha,W0,M,CS,DS)!=0)
			alert("***ECDSA Verification Failed");
		else mywindow.document.write("ECDSA Signature/Verification succeeded "+  "<br>");
	}
}


/* Test RSA */
/* test driver and function exerciser for RSA API Functions */


// RSA2048 context
function rsa2048() {
	var ctx = new CTX('RSA2048');

	var i,j=0,res;
	var result;

	var sha=ctx.RSA.HASH_TYPE;

	var message="Hello World\n";

	var pub=new ctx.rsa_public_key(ctx.FF.FFLEN);
	var priv=new ctx.rsa_private_key(ctx.FF.HFLEN);

	var ML=[];
	var C=[];
	var S=[];
	
	var RAW=[];
	var rng=new ctx.RAND();

	rng.clean();
	for (i=0;i<100;i++) RAW[i]=i;

	rng.seed(100,RAW);

	mywindow=window.open();

	var start,end,time;
	start=new Date().getTime();
	mywindow.document.write("<br> Generating RSA public/private key pair (slow!)  <br>");
	ctx.RSA.KEY_PAIR(rng,65537,priv,pub);
	end=new Date().getTime();
	time=end-start;
	mywindow.document.write("Time in ms= "+time+"<br>");

	var M=ctx.RSA.stringtobytes(message);  
	mywindow.document.write("Encrypting test string <br>");

	var E=ctx.RSA.OAEP_ENCODE(sha,M,rng,null); /* OAEP encode message m to e  */
	mywindow.document.write("Encoding= 0x" + ctx.RSA.bytestohex(E) + "<br>");  

	mywindow.document.write("Public key= 0x"+pub.n.toString() + "<br>"); 

	start=new Date().getTime();	
	ctx.RSA.ENCRYPT(pub,E,C);     /* encrypt encoded message */
	end=new Date().getTime();	
	time=end-start;
	mywindow.document.write("Time in ms= "+time+"<br>");

	mywindow.document.write("Ciphertext= 0x" + ctx.RSA.bytestohex(C) + "<br>");  

	mywindow.document.write("Decrypting test string <br>");
	start=new Date().getTime();	
	ctx.RSA.DECRYPT(priv,C,ML); 
	end=new Date().getTime();
	time=end-start;
	mywindow.document.write("Time in ms= "+time+"<br>");

	var cmp=true;
	if (E.length!=ML.length) cmp=false;
	else
	{
		for (var j=0;j<E.length;j++)
			if (E[j]!=ML[j]) cmp=false;
	}
	if (cmp) mywindow.document.write("Decryption is OK <br>");
	else mywindow.document.write("Decryption Failed <br>");

	var MS=ctx.RSA.OAEP_DECODE(sha,null,ML); /* OAEP decode message  */
	mywindow.document.write("Decoding= 0x" + ctx.RSA.bytestohex(MS) + "<br>");  

	mywindow.document.write("message= "+ctx.RSA.bytestostring(MS) + "<br>");  


	mywindow.document.write("Signing message <br>");
	ctx.RSA.PKCS15(sha,M,C);

	ctx.RSA.DECRYPT(priv,C,S); /* create signature in S */ 

	mywindow.document.write("Signature= 0x" + ctx.RSA.bytestohex(S) + "<br>");  

	ctx.RSA.ENCRYPT(pub,S,ML); 

	cmp=true;
	if (C.length!=ML.length) cmp=false;
	else
	{
		for (var j=0;j<C.length;j++)
			if (C[j]!=ML[j]) cmp=false;
	}
	if (cmp) mywindow.document.write("Signature is valid <br>");
	else mywindow.document.write("Signature is INVALID <br>");

	ctx.RSA.PRIVATE_KEY_KILL(priv);


}

/* Test M-Pin */

// BN254 context
function bn254() {
	var ctx = new CTX('BN254');
	mywindow=window.open();

	mywindow.document.write("<br> BN254 Pairing-Friendly Curve "+  "<br>");

	var i,res;
	var result;

	var EGS=ctx.MPIN.EGS;
	var EFS=ctx.MPIN.EFS;
	var EAS=ctx.ECP.AESKEY;

	var sha=ctx.ECP.HASH_TYPE;

	var G1S=2*EFS+1; /* Group 1 Size */
	var G2S=4*EFS; /* Group 2 Size */

	var S=[];
	var SST=[];
	var TOKEN = [];
	var PERMIT = [];
	var SEC = [];
	var xID = [];
	var xCID = [];
	var X= [];
	var Y= [];
	var E=[];
	var F=[];
	var HCID=[];
	var HID=[];
	var HTID=[];

	var G1=[];
	var G2=[];
	var R=[];
	var Z=[];
	var W=[];
	var T=[];
	var CK=[];
	var SK=[];

	var HSID=[];

/* Set configuration */
	var PERMITS=true;
	var PINERROR=true;
	var FULL=true;
    var ONE_PASS=false;

	var RAW=[];
	var rng=new ctx.RAND();

	rng.clean();
	for (i=0;i<100;i++) RAW[i]=i;

	rng.seed(100,RAW);

/* Trusted Authority set-up */
	ctx.MPIN.RANDOM_GENERATE(rng,S);
	mywindow.document.write("M-Pin Master Secret s: 0x"+ctx.MPIN.bytestostring(S) + "<br>");
 
 /* Create Client Identity */
 	var IDstr = "testUser@miracl.com";
	var CLIENT_ID = ctx.MPIN.asciitobytes(IDstr);  
	HCID=ctx.MPIN.HASH_ID(sha,CLIENT_ID);  /* Either Client or TA calculates Hash(ID) - you decide! */
		
	mywindow.document.write("Client ID= "+ctx.MPIN.bytestostring(CLIENT_ID) + "<br>");

/* Client and Server are issued secrets by DTA */
	ctx.MPIN.GET_SERVER_SECRET(S,SST);
	mywindow.document.write("Server Secret SS: 0x"+ctx.MPIN.bytestostring(SST) + "<br>");

	ctx.MPIN.GET_CLIENT_SECRET(S,HCID,TOKEN);
	mywindow.document.write("Client Secret CS: 0x"+ctx.MPIN.bytestostring(TOKEN) + "<br>");     
	
/* Client extracts PIN from secret to create Token */
	var pin=1234;
	mywindow.document.write("Client extracts PIN= "+pin + "<br>"); 
	var rtn=ctx.MPIN.EXTRACT_PIN(sha,CLIENT_ID,pin,TOKEN);
	if (rtn != 0)
		mywindow.document.write("Failed to extract PIN " + "<br>");  

	mywindow.document.write("Client Token TK: 0x"+ctx.MPIN.bytestostring(TOKEN) + "<br>");        

	if (FULL)
	{
		ctx.MPIN.PRECOMPUTE(TOKEN,HCID,G1,G2);
	}

	var date;
	if (PERMITS)
	{
		date=ctx.MPIN.today();
/* Client gets "Time Token" permit from DTA */ 	
		ctx.MPIN.GET_CLIENT_PERMIT(sha,date,S,HCID,PERMIT);
		mywindow.document.write("Time Permit TP: 0x"+ctx.MPIN.bytestostring(PERMIT) + "<br>");   

/* This encoding makes Time permit look random - Elligator squared */
		ctx.MPIN.ENCODING(rng,PERMIT);
		mywindow.document.write("Encoded Time Permit TP: 0x"+ctx.MPIN.bytestostring(PERMIT) + "<br>");   
		ctx.MPIN.DECODING(PERMIT);
		mywindow.document.write("Decoded Time Permit TP: 0x"+ctx.MPIN.bytestostring(PERMIT) + "<br>");   
	}
	else date=0;

	pin=parseInt(mywindow.prompt("Enter PIN= "));

/* Set date=0 and PERMIT=null if time permits not in use

Client First pass: Inputs CLIENT_ID, optional RNG, pin, TOKEN and PERMIT. Output xID = x.H(CLIENT_ID) and re-combined secret SEC
If PERMITS are is use, then date!=0 and PERMIT is added to secret and xCID = x.(H(CLIENT_ID)+H_T(date|H(CLIENT_ID)))
Random value x is supplied externally if RNG=null, otherwise generated and passed out by RNG

If Time Permits OFF set xCID = null, HTID=null and use xID and HID only
If Time permits are ON, AND pin error detection is required then all of xID, xCID, HID and HTID are required
If Time permits are ON, AND pin error detection is NOT required, set xID=null, HID=null and use xCID and HTID only.


*/
	var pxID=xID;
	var pxCID=xCID;
	var pHID=HID;
	var pHTID=HTID;
	var pE=E;
	var pF=F;
	var pPERMIT=PERMIT;
	var prHID;

	if (date!=0)
	{
		prHID=pHTID;
		if (!PINERROR)
		{
			pxID=null;
			//	pHID=null;
		}
	}
	else
	{
		prHID=pHID;
		pPERMIT=null;
		pxCID=null;
		pHTID=null;
	}
	if (!PINERROR)
	{
		pE=null;
		pF=null;
	}

	if (ONE_PASS)
	{
		mywindow.document.write("MPIN Single Pass " + "<br>");   
		timeValue = ctx.MPIN.GET_TIME();
		mywindow.document.write("Epoch " + timeValue + "<br>");   

		rtn=ctx.MPIN.CLIENT(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT,timeValue,Y);

		if (rtn != 0)
		mywindow.document.write("FAILURE: CLIENT rtn: " + rtn + "<br>");   

		if (FULL)
		{
			HCID=ctx.MPIN.HASH_ID(sha,CLIENT_ID);
			ctx.MPIN.GET_G1_MULTIPLE(rng,1,R,HCID,Z);  /* Also Send Z=r.ID to Server, remember random r */
		}

		rtn=ctx.MPIN.SERVER(sha,date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF,CLIENT_ID,timeValue);
		if (rtn != 0)
			mywindow.document.write("FAILURE: SERVER rtn: " + rtn+ "<br>");  

		if (FULL)
		{
			HSID=ctx.MPIN.HASH_ID(sha,CLIENT_ID);
			ctx.MPIN.GET_G1_MULTIPLE(rng,0,W,prHID,T);  /* Also send T=w.ID to client, remember random w  */
		}
	}
	else 
	{
		mywindow.document.write("MPIN Multi Pass " + "<br>");   
		rtn=ctx.MPIN.CLIENT_1(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT);
		if (rtn != 0)
			mywindow.document.write("FAILURE: CLIENT_1 rtn: " + rtn + "<br>");   
  
		if (FULL)
		{
			HCID=ctx.MPIN.HASH_ID(sha,CLIENT_ID);
			ctx.MPIN.GET_G1_MULTIPLE(rng,1,R,HCID,Z);  /* Also Send Z=r.ID to Server, remember random r */
		}
    
  /* Server calculates H(ID) and H(T|H(ID)) (if time permits enabled), and maps them to points on the curve HID and HTID resp. */
		ctx.MPIN.SERVER_1(sha,date,CLIENT_ID,pHID,pHTID);
    
  /* Server generates Random number Y and sends it to Client */
		ctx.MPIN.RANDOM_GENERATE(rng,Y);
    
		if (FULL)
		{
			HSID=ctx.MPIN.HASH_ID(sha,CLIENT_ID);
			ctx.MPIN.GET_G1_MULTIPLE(rng,0,W,prHID,T);  /* Also send T=w.ID to client, remember random w  */
		}
    
  /* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
		rtn=ctx.MPIN.CLIENT_2(X,Y,SEC);
		if (rtn != 0)
			mywindow.document.write("FAILURE: CLIENT_2 rtn: " + rtn + "<br>");  
  /* Server Second pass. Inputs hashed client id, random Y, -(x+y)*SEC, xID and xCID and Server secret SST. E and F help kangaroos to find error. */
  /* If PIN error not required, set E and F = NULL */
		rtn=ctx.MPIN.SERVER_2(date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF);
    
		if (rtn != 0)
			mywindow.document.write("FAILURE: SERVER_2 rtn: " + rtn+ "<br>");  
    
	}
    		  

	if (rtn == ctx.MPIN.BAD_PIN)
	{
		mywindow.document.write("Server says - Bad Pin. I don't know you. Feck off." + "<br>"); 
		if (PINERROR)
		{
			var err=ctx.MPIN.KANGAROO(E,F);
			if (err!=0) mywindow.document.write("(Client PIN is out by "+err + ")<br>");
		}
	}
	else 
	{
		mywindow.document.write("Server says - PIN is good! You really are "+IDstr + "<br>"); 
		if (FULL)
		{
			H=ctx.MPIN.HASH_ALL(sha,HCID,pxID,pxCID,SEC,Y,Z,T);
			ctx.MPIN.CLIENT_KEY(sha,G1,G2,pin,R,X,H,T,CK);
			
			mywindow.document.write("Client Key =  0x"+ctx.MPIN.bytestostring(CK) + "<br>");    
			H=ctx.MPIN.HASH_ALL(sha,HSID,pxID,pxCID,SEC,Y,Z,T);
			ctx.MPIN.SERVER_KEY(sha,Z,SST,W,H,pHID,pxID,pxCID,SK);
			mywindow.document.write("Server Key =  0x"+ctx.MPIN.bytestostring(SK) + "<br>");    
		}
	}

}

// BLS383 context
function bls383() {
	var ctx = new CTX('BLS383');
	mywindow=window.open();

	mywindow.document.write("<br> BLS383 Pairing-Friendly Curve "+  "<br>");

	var i,res;
	var result;

	var EGS=ctx.MPIN.EGS;
	var EFS=ctx.MPIN.EFS;
	var EAS=ctx.ECP.AESKEY;

	var sha=ctx.ECP.HASH_TYPE;

	var G1S=2*EFS+1; /* Group 1 Size */
	var G2S=4*EFS; /* Group 2 Size */

	var S=[];
	var SST=[];
	var TOKEN = [];
	var PERMIT = [];
	var SEC = [];
	var xID = [];
	var xCID = [];
	var X= [];
	var Y= [];
	var E=[];
	var F=[];
	var HCID=[];
	var HID=[];
	var HTID=[];

	var G1=[];
	var G2=[];
	var R=[];
	var Z=[];
	var W=[];
	var T=[];
	var CK=[];
	var SK=[];

	var HSID=[];

/* Set configuration */
	var PERMITS=true;
	var PINERROR=true;
	var FULL=true;
    var ONE_PASS=false;

	var RAW=[];
	var rng=new ctx.RAND();

	rng.clean();
	for (i=0;i<100;i++) RAW[i]=i;

	rng.seed(100,RAW);


/* Trusted Authority set-up */
	ctx.MPIN.RANDOM_GENERATE(rng,S);
	mywindow.document.write("M-Pin Master Secret s: 0x"+ctx.MPIN.bytestostring(S) + "<br>");
 
 /* Create Client Identity */
 	var IDstr = "testUser@miracl.com";
	var CLIENT_ID = ctx.MPIN.asciitobytes(IDstr);  
	HCID=ctx.MPIN.HASH_ID(sha,CLIENT_ID);  /* Either Client or TA calculates Hash(ID) - you decide! */
		
	mywindow.document.write("Client ID= "+ctx.MPIN.bytestostring(CLIENT_ID) + "<br>");

/* Client and Server are issued secrets by DTA */
	ctx.MPIN.GET_SERVER_SECRET(S,SST);
	mywindow.document.write("Server Secret SS: 0x"+ctx.MPIN.bytestostring(SST) + "<br>");

	ctx.MPIN.GET_CLIENT_SECRET(S,HCID,TOKEN);
	mywindow.document.write("Client Secret CS: 0x"+ctx.MPIN.bytestostring(TOKEN) + "<br>");     
	
/* Client extracts PIN from secret to create Token */
	var pin=1234;
	mywindow.document.write("Client extracts PIN= "+pin + "<br>"); 
	var rtn=ctx.MPIN.EXTRACT_PIN(sha,CLIENT_ID,pin,TOKEN);
	if (rtn != 0)
		mywindow.document.write("Failed to extract PIN " + "<br>");  

	mywindow.document.write("Client Token TK: 0x"+ctx.MPIN.bytestostring(TOKEN) + "<br>");        

	if (FULL)
	{
		ctx.MPIN.PRECOMPUTE(TOKEN,HCID,G1,G2);
	}

	var date;
	if (PERMITS)
	{
		date=ctx.MPIN.today();
/* Client gets "Time Token" permit from DTA */ 	
		ctx.MPIN.GET_CLIENT_PERMIT(sha,date,S,HCID,PERMIT);
		mywindow.document.write("Time Permit TP: 0x"+ctx.MPIN.bytestostring(PERMIT) + "<br>");   

/* This encoding makes Time permit look random - Elligator squared */
		ctx.MPIN.ENCODING(rng,PERMIT);
		mywindow.document.write("Encoded Time Permit TP: 0x"+ctx.MPIN.bytestostring(PERMIT) + "<br>");   
		ctx.MPIN.DECODING(PERMIT);
		mywindow.document.write("Decoded Time Permit TP: 0x"+ctx.MPIN.bytestostring(PERMIT) + "<br>");   
	}
	else date=0;

	pin=parseInt(mywindow.prompt("Enter PIN= "));

/* Set date=0 and PERMIT=null if time permits not in use

Client First pass: Inputs CLIENT_ID, optional RNG, pin, TOKEN and PERMIT. Output xID = x.H(CLIENT_ID) and re-combined secret SEC
If PERMITS are is use, then date!=0 and PERMIT is added to secret and xCID = x.(H(CLIENT_ID)+H_T(date|H(CLIENT_ID)))
Random value x is supplied externally if RNG=null, otherwise generated and passed out by RNG

If Time Permits OFF set xCID = null, HTID=null and use xID and HID only
If Time permits are ON, AND pin error detection is required then all of xID, xCID, HID and HTID are required
If Time permits are ON, AND pin error detection is NOT required, set xID=null, HID=null and use xCID and HTID only.


*/
	var pxID=xID;
	var pxCID=xCID;
	var pHID=HID;
	var pHTID=HTID;
	var pE=E;
	var pF=F;
	var pPERMIT=PERMIT;
	var prHID;

	if (date!=0)
	{
		prHID=pHTID;
		if (!PINERROR)
		{
			pxID=null;
			//	pHID=null;
		}
	}
	else
	{
		prHID=pHID;
		pPERMIT=null;
		pxCID=null;
		pHTID=null;
	}
	if (!PINERROR)
	{
		pE=null;
		pF=null;
	}

	if (ONE_PASS)
	{
		mywindow.document.write("MPIN Single Pass " + "<br>");   
		timeValue = ctx.MPIN.GET_TIME();
		mywindow.document.write("Epoch " + timeValue + "<br>");   

		rtn=ctx.MPIN.CLIENT(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT,timeValue,Y);

		if (rtn != 0)
		mywindow.document.write("FAILURE: CLIENT rtn: " + rtn + "<br>");   

		if (FULL)
		{
			HCID=ctx.MPIN.HASH_ID(sha,CLIENT_ID);
			ctx.MPIN.GET_G1_MULTIPLE(rng,1,R,HCID,Z);  /* Also Send Z=r.ID to Server, remember random r */
		}

		rtn=ctx.MPIN.SERVER(sha,date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF,CLIENT_ID,timeValue);
		if (rtn != 0)
			mywindow.document.write("FAILURE: SERVER rtn: " + rtn+ "<br>");  

		if (FULL)
		{
			HSID=ctx.MPIN.HASH_ID(sha,CLIENT_ID);
			ctx.MPIN.GET_G1_MULTIPLE(rng,0,W,prHID,T);  /* Also send T=w.ID to client, remember random w  */
		}
	}
	else 
	{
		mywindow.document.write("MPIN Multi Pass " + "<br>");   
		rtn=ctx.MPIN.CLIENT_1(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT);
		if (rtn != 0)
			mywindow.document.write("FAILURE: CLIENT_1 rtn: " + rtn + "<br>");   
  
		if (FULL)
		{
			HCID=ctx.MPIN.HASH_ID(sha,CLIENT_ID);
			ctx.MPIN.GET_G1_MULTIPLE(rng,1,R,HCID,Z);  /* Also Send Z=r.ID to Server, remember random r */
		}
    
  /* Server calculates H(ID) and H(T|H(ID)) (if time permits enabled), and maps them to points on the curve HID and HTID resp. */
		ctx.MPIN.SERVER_1(sha,date,CLIENT_ID,pHID,pHTID);
    
  /* Server generates Random number Y and sends it to Client */
		ctx.MPIN.RANDOM_GENERATE(rng,Y);
    
		if (FULL)
		{
			HSID=ctx.MPIN.HASH_ID(sha,CLIENT_ID);
			ctx.MPIN.GET_G1_MULTIPLE(rng,0,W,prHID,T);  /* Also send T=w.ID to client, remember random w  */
		}
    
  /* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
		rtn=ctx.MPIN.CLIENT_2(X,Y,SEC);
		if (rtn != 0)
			mywindow.document.write("FAILURE: CLIENT_2 rtn: " + rtn + "<br>");  
  /* Server Second pass. Inputs hashed client id, random Y, -(x+y)*SEC, xID and xCID and Server secret SST. E and F help kangaroos to find error. */
  /* If PIN error not required, set E and F = NULL */
		rtn=ctx.MPIN.SERVER_2(date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF);
    
		if (rtn != 0)
			mywindow.document.write("FAILURE: SERVER_2 rtn: " + rtn+ "<br>");  
    
	}
    		  

	if (rtn == ctx.MPIN.BAD_PIN)
	{
		mywindow.document.write("Server says - Bad Pin. I don't know you. Feck off." + "<br>"); 
		if (PINERROR)
		{
			var err=ctx.MPIN.KANGAROO(E,F);
			if (err!=0) mywindow.document.write("(Client PIN is out by "+err + ")<br>");
		}
	}
	else 
	{
		mywindow.document.write("Server says - PIN is good! You really are "+IDstr + "<br>"); 
		if (FULL)
		{
			H=ctx.MPIN.HASH_ALL(sha,HCID,pxID,pxCID,SEC,Y,Z,T);
			ctx.MPIN.CLIENT_KEY(sha,G1,G2,pin,R,X,H,T,CK);
			
			mywindow.document.write("Client Key =  0x"+ctx.MPIN.bytestostring(CK) + "<br>");    
			H=ctx.MPIN.HASH_ALL(sha,HSID,pxID,pxCID,SEC,Y,Z,T);
			ctx.MPIN.SERVER_KEY(sha,Z,SST,W,H,pHID,pxID,pxCID,SK);
			mywindow.document.write("Server Key =  0x"+ctx.MPIN.bytestostring(SK) + "<br>");    
		}
	}

}



// BLS24 context
function bls24() {
	var ctx = new CTX('BLS24');
	mywindow=window.open();

	mywindow.document.write("<br> BLS24 Pairing-Friendly Curve "+  "<br>");

	var i,res;
	var result;

	var EGS=ctx.MPIN192.EGS;
	var EFS=ctx.MPIN192.EFS;
	var EAS=ctx.ECP.AESKEY;

	var sha=ctx.ECP.HASH_TYPE;

	var G1S=2*EFS+1; /* Group 1 Size */
	var G2S=8*EFS; /* Group 2 Size */   /**/

	var S=[];
	var SST=[];
	var TOKEN = [];
	var PERMIT = [];
	var SEC = [];
	var xID = [];
	var xCID = [];
	var X= [];
	var Y= [];
	var E=[];
	var F=[];
	var HCID=[];
	var HID=[];
	var HTID=[];

	var G1=[];
	var G2=[];
	var R=[];
	var Z=[];
	var W=[];
	var T=[];
	var CK=[];
	var SK=[];

	var HSID=[];

/* Set configuration */
	var PERMITS=true;
	var PINERROR=true;
	var FULL=true;
    var ONE_PASS=false;

	var RAW=[];
	var rng=new ctx.RAND();

	rng.clean();
	for (i=0;i<100;i++) RAW[i]=i;

	rng.seed(100,RAW);

/* Trusted Authority set-up */
	ctx.MPIN192.RANDOM_GENERATE(rng,S);
	mywindow.document.write("M-Pin Master Secret s: 0x"+ctx.MPIN192.bytestostring(S) + "<br>");
 
 /* Create Client Identity */
 	var IDstr = "testUser@miracl.com";
	var CLIENT_ID = ctx.MPIN192.asciitobytes(IDstr);  
	HCID=ctx.MPIN192.HASH_ID(sha,CLIENT_ID);  /* Either Client or TA calculates Hash(ID) - you decide! */
		
	mywindow.document.write("Client ID= "+ctx.MPIN192.bytestostring(CLIENT_ID) + "<br>");

/* Client and Server are issued secrets by DTA */
	ctx.MPIN192.GET_SERVER_SECRET(S,SST);
	mywindow.document.write("Server Secret SS: 0x"+ctx.MPIN192.bytestostring(SST) + "<br>");

	ctx.MPIN192.GET_CLIENT_SECRET(S,HCID,TOKEN);
	mywindow.document.write("Client Secret CS: 0x"+ctx.MPIN192.bytestostring(TOKEN) + "<br>");     
	
/* Client extracts PIN from secret to create Token */
	var pin=1234;
	mywindow.document.write("Client extracts PIN= "+pin + "<br>"); 
	var rtn=ctx.MPIN192.EXTRACT_PIN(sha,CLIENT_ID,pin,TOKEN);
	if (rtn != 0)
		mywindow.document.write("Failed to extract PIN " + "<br>");  

	mywindow.document.write("Client Token TK: 0x"+ctx.MPIN192.bytestostring(TOKEN) + "<br>");        

	if (FULL)
	{
		ctx.MPIN192.PRECOMPUTE(TOKEN,HCID,G1,G2);
	}

	var date;
	if (PERMITS)
	{
		date=ctx.MPIN192.today();
/* Client gets "Time Token" permit from DTA */ 	
		ctx.MPIN192.GET_CLIENT_PERMIT(sha,date,S,HCID,PERMIT);
		mywindow.document.write("Time Permit TP: 0x"+ctx.MPIN192.bytestostring(PERMIT) + "<br>");   

/* This encoding makes Time permit look random - Elligator squared */
		ctx.MPIN192.ENCODING(rng,PERMIT);
		mywindow.document.write("Encoded Time Permit TP: 0x"+ctx.MPIN192.bytestostring(PERMIT) + "<br>");   
		ctx.MPIN192.DECODING(PERMIT);
		mywindow.document.write("Decoded Time Permit TP: 0x"+ctx.MPIN192.bytestostring(PERMIT) + "<br>");   
	}
	else date=0;

	pin=parseInt(mywindow.prompt("Enter PIN= "));

/* Set date=0 and PERMIT=null if time permits not in use

Client First pass: Inputs CLIENT_ID, optional RNG, pin, TOKEN and PERMIT. Output xID = x.H(CLIENT_ID) and re-combined secret SEC
If PERMITS are is use, then date!=0 and PERMIT is added to secret and xCID = x.(H(CLIENT_ID)+H_T(date|H(CLIENT_ID)))
Random value x is supplied externally if RNG=null, otherwise generated and passed out by RNG

If Time Permits OFF set xCID = null, HTID=null and use xID and HID only
If Time permits are ON, AND pin error detection is required then all of xID, xCID, HID and HTID are required
If Time permits are ON, AND pin error detection is NOT required, set xID=null, HID=null and use xCID and HTID only.


*/
	var pxID=xID;
	var pxCID=xCID;
	var pHID=HID;
	var pHTID=HTID;
	var pE=E;
	var pF=F;
	var pPERMIT=PERMIT;
	var prHID;

	if (date!=0)
	{
		prHID=pHTID;
		if (!PINERROR)
		{
			pxID=null;
			//	pHID=null;
		}
	}
	else
	{
		prHID=pHID;
		pPERMIT=null;
		pxCID=null;
		pHTID=null;
	}
	if (!PINERROR)
	{
		pE=null;
		pF=null;
	}

	if (ONE_PASS)
	{
		mywindow.document.write("MPIN Single Pass " + "<br>");   
		timeValue = ctx.MPIN192.GET_TIME();
		mywindow.document.write("Epoch " + timeValue + "<br>");   

		rtn=ctx.MPIN192.CLIENT(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT,timeValue,Y);

		if (rtn != 0)
		mywindow.document.write("FAILURE: CLIENT rtn: " + rtn + "<br>");   

		if (FULL)
		{
			HCID=ctx.MPIN192.HASH_ID(sha,CLIENT_ID);
			ctx.MPIN192.GET_G1_MULTIPLE(rng,1,R,HCID,Z);  /* Also Send Z=r.ID to Server, remember random r */
		}

		rtn=ctx.MPIN192.SERVER(sha,date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF,CLIENT_ID,timeValue);
		if (rtn != 0)
			mywindow.document.write("FAILURE: SERVER rtn: " + rtn+ "<br>");  

		if (FULL)
		{
			HSID=ctx.MPIN192.HASH_ID(sha,CLIENT_ID);
			ctx.MPIN192.GET_G1_MULTIPLE(rng,0,W,prHID,T);  /* Also send T=w.ID to client, remember random w  */
		}
	}
	else 
	{
		mywindow.document.write("MPIN Multi Pass " + "<br>");   
		rtn=ctx.MPIN192.CLIENT_1(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT);
		if (rtn != 0)
			mywindow.document.write("FAILURE: CLIENT_1 rtn: " + rtn + "<br>");   
  
		if (FULL)
		{
			HCID=ctx.MPIN192.HASH_ID(sha,CLIENT_ID);
			ctx.MPIN192.GET_G1_MULTIPLE(rng,1,R,HCID,Z);  /* Also Send Z=r.ID to Server, remember random r */
		}
    
  /* Server calculates H(ID) and H(T|H(ID)) (if time permits enabled), and maps them to points on the curve HID and HTID resp. */
		ctx.MPIN192.SERVER_1(sha,date,CLIENT_ID,pHID,pHTID);
    
  /* Server generates Random number Y and sends it to Client */
		ctx.MPIN192.RANDOM_GENERATE(rng,Y);
    
		if (FULL)
		{
			HSID=ctx.MPIN192.HASH_ID(sha,CLIENT_ID);
			ctx.MPIN192.GET_G1_MULTIPLE(rng,0,W,prHID,T);  /* Also send T=w.ID to client, remember random w  */
		}
    
  /* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
		rtn=ctx.MPIN192.CLIENT_2(X,Y,SEC);
		if (rtn != 0)
			mywindow.document.write("FAILURE: CLIENT_2 rtn: " + rtn + "<br>");  
  /* Server Second pass. Inputs hashed client id, random Y, -(x+y)*SEC, xID and xCID and Server secret SST. E and F help kangaroos to find error. */
  /* If PIN error not required, set E and F = NULL */
		rtn=ctx.MPIN192.SERVER_2(date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF);
    
		if (rtn != 0)
			mywindow.document.write("FAILURE: SERVER_2 rtn: " + rtn+ "<br>");  
    
	}
    		  

	if (rtn == ctx.MPIN192.BAD_PIN)
	{
		mywindow.document.write("Server says - Bad Pin. I don't know you. Feck off." + "<br>"); 
		if (PINERROR)
		{
			var err=ctx.MPIN192.KANGAROO(E,F);
			if (err!=0) mywindow.document.write("(Client PIN is out by "+err + ")<br>");
		}
	}
	else 
	{
		mywindow.document.write("Server says - PIN is good! You really are "+IDstr + "<br>"); 
		if (FULL)
		{
			H=ctx.MPIN192.HASH_ALL(sha,HCID,pxID,pxCID,SEC,Y,Z,T);
			ctx.MPIN192.CLIENT_KEY(sha,G1,G2,pin,R,X,H,T,CK);
			
			mywindow.document.write("Client Key =  0x"+ctx.MPIN192.bytestostring(CK) + "<br>");    
			H=ctx.MPIN192.HASH_ALL(sha,HSID,pxID,pxCID,SEC,Y,Z,T);
			ctx.MPIN192.SERVER_KEY(sha,Z,SST,W,H,pHID,pxID,pxCID,SK);
			mywindow.document.write("Server Key =  0x"+ctx.MPIN192.bytestostring(SK) + "<br>");    
		}
	}

} 

// BLS48 context
function bls48() {
	var ctx = new CTX('BLS48');
	mywindow=window.open();

	mywindow.document.write("<br> BLS48 Pairing-Friendly Curve "+  "<br>");

	var i,res;
	var result;

	var EGS=ctx.MPIN256.EGS;
	var EFS=ctx.MPIN256.EFS;
	var EAS=ctx.ECP.AESKEY;

	var sha=ctx.ECP.HASH_TYPE;

	var G1S=2*EFS+1; // Group 1 Size 
	var G2S=16*EFS; // Group 2 Size    **

	var S=[];
	var SST=[];
	var TOKEN = [];
	var PERMIT = [];
	var SEC = [];
	var xID = [];
	var xCID = [];
	var X= [];
	var Y= [];
	var E=[];
	var F=[];
	var HCID=[];
	var HID=[];
	var HTID=[];

	var G1=[];
	var G2=[];
	var R=[];
	var Z=[];
	var W=[];
	var T=[];
	var CK=[];
	var SK=[];

	var HSID=[];

// Set configuration 
	var PERMITS=true;
	var PINERROR=true;
	var FULL=true;
    var ONE_PASS=false;

	var RAW=[];
	var rng=new ctx.RAND();

	rng.clean();
	for (i=0;i<100;i++) RAW[i]=i;

	rng.seed(100,RAW);

// Trusted Authority set-up 
	ctx.MPIN256.RANDOM_GENERATE(rng,S);

	mywindow.document.write("M-Pin Master Secret s: 0x"+ctx.MPIN256.bytestostring(S) + "<br>");
 // Create Client Identity 
 	var IDstr = "testUser@miracl.com";
	var CLIENT_ID = ctx.MPIN256.asciitobytes(IDstr);  
	HCID=ctx.MPIN256.HASH_ID(sha,CLIENT_ID);  // Either Client or TA calculates Hash(ID) - you decide! 
		
	mywindow.document.write("Client ID= "+ctx.MPIN256.bytestostring(CLIENT_ID) + "<br>");

// Client and Server are issued secrets by DTA 
	ctx.MPIN256.GET_SERVER_SECRET(S,SST);
	mywindow.document.write("Server Secret SS: 0x"+ctx.MPIN256.bytestostring(SST) + "<br>");

	ctx.MPIN256.GET_CLIENT_SECRET(S,HCID,TOKEN);
	mywindow.document.write("Client Secret CS: 0x"+ctx.MPIN256.bytestostring(TOKEN) + "<br>");     
	
// Client extracts PIN from secret to create Token 
	var pin=1234;
	mywindow.document.write("Client extracts PIN= "+pin + "<br>"); 
	var rtn=ctx.MPIN256.EXTRACT_PIN(sha,CLIENT_ID,pin,TOKEN);
	if (rtn != 0)
		mywindow.document.write("Failed to extract PIN " + "<br>");  

	mywindow.document.write("Client Token TK: 0x"+ctx.MPIN256.bytestostring(TOKEN) + "<br>");        

	if (FULL)
	{
		ctx.MPIN256.PRECOMPUTE(TOKEN,HCID,G1,G2);
	}

	var date;
	if (PERMITS)
	{
		date=ctx.MPIN256.today();
// Client gets "Time Token" permit from DTA  	
		ctx.MPIN256.GET_CLIENT_PERMIT(sha,date,S,HCID,PERMIT);
		mywindow.document.write("Time Permit TP: 0x"+ctx.MPIN256.bytestostring(PERMIT) + "<br>");   

// This encoding makes Time permit look random - Elligator squared 
		ctx.MPIN256.ENCODING(rng,PERMIT);
		mywindow.document.write("Encoded Time Permit TP: 0x"+ctx.MPIN256.bytestostring(PERMIT) + "<br>");   
		ctx.MPIN256.DECODING(PERMIT);
		mywindow.document.write("Decoded Time Permit TP: 0x"+ctx.MPIN256.bytestostring(PERMIT) + "<br>");   
	}
	else date=0;

	pin=parseInt(mywindow.prompt("Enter PIN= "));

// Set date=0 and PERMIT=null if time permits not in use

//Client First pass: Inputs CLIENT_ID, optional RNG, pin, TOKEN and PERMIT. Output xID = x.H(CLIENT_ID) and re-combined secret SEC
//If PERMITS are is use, then date!=0 and PERMIT is added to secret and xCID = x.(H(CLIENT_ID)+H_T(date|H(CLIENT_ID)))
//Random value x is supplied externally if RNG=null, otherwise generated and passed out by RNG

//If Time Permits OFF set xCID = null, HTID=null and use xID and HID only
//If Time permits are ON, AND pin error detection is required then all of xID, xCID, HID and HTID are required
//If Time permits are ON, AND pin error detection is NOT required, set xID=null, HID=null and use xCID and HTID only.


	var pxID=xID;
	var pxCID=xCID;
	var pHID=HID;
	var pHTID=HTID;
	var pE=E;
	var pF=F;
	var pPERMIT=PERMIT;
	var prHID;

	if (date!=0)
	{
		prHID=pHTID;
		if (!PINERROR)
		{
			pxID=null;
			//	pHID=null;
		}
	}
	else
	{
		prHID=pHID;
		pPERMIT=null;
		pxCID=null;
		pHTID=null;
	}
	if (!PINERROR)
	{
		pE=null;
		pF=null;
	}

	if (ONE_PASS)
	{
		mywindow.document.write("MPIN Single Pass " + "<br>");   
		timeValue = ctx.MPIN256.GET_TIME();
		mywindow.document.write("Epoch " + timeValue + "<br>");   

		rtn=ctx.MPIN256.CLIENT(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT,timeValue,Y);

		if (rtn != 0)
		mywindow.document.write("FAILURE: CLIENT rtn: " + rtn + "<br>");   

		if (FULL)
		{
			HCID=ctx.MPIN256.HASH_ID(sha,CLIENT_ID);
			ctx.MPIN256.GET_G1_MULTIPLE(rng,1,R,HCID,Z);  // Also Send Z=r.ID to Server, remember random r 
		}

		rtn=ctx.MPIN256.SERVER(sha,date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF,CLIENT_ID,timeValue);
		if (rtn != 0)
			mywindow.document.write("FAILURE: SERVER rtn: " + rtn+ "<br>");  

		if (FULL)
		{
			HSID=ctx.MPIN256.HASH_ID(sha,CLIENT_ID);
			ctx.MPIN256.GET_G1_MULTIPLE(rng,0,W,prHID,T);  // Also send T=w.ID to client, remember random w  
		}
	}
	else 
	{
		mywindow.document.write("MPIN Multi Pass " + "<br>");   
		rtn=ctx.MPIN256.CLIENT_1(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT);
		if (rtn != 0)
			mywindow.document.write("FAILURE: CLIENT_1 rtn: " + rtn + "<br>");   
  
		if (FULL)
		{
			HCID=ctx.MPIN256.HASH_ID(sha,CLIENT_ID);
			ctx.MPIN256.GET_G1_MULTIPLE(rng,1,R,HCID,Z);  // Also Send Z=r.ID to Server, remember random r 
		}
    
  // Server calculates H(ID) and H(T|H(ID)) (if time permits enabled), and maps them to points on the curve HID and HTID resp. 
		ctx.MPIN256.SERVER_1(sha,date,CLIENT_ID,pHID,pHTID);
    
  // Server generates Random number Y and sends it to Client 
		ctx.MPIN256.RANDOM_GENERATE(rng,Y);
    
		if (FULL)
		{
			HSID=ctx.MPIN256.HASH_ID(sha,CLIENT_ID);
			ctx.MPIN256.GET_G1_MULTIPLE(rng,0,W,prHID,T);  // Also send T=w.ID to client, remember random w  
		}
    
  // Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC 
		rtn=ctx.MPIN256.CLIENT_2(X,Y,SEC);
		if (rtn != 0)
			mywindow.document.write("FAILURE: CLIENT_2 rtn: " + rtn + "<br>");  
  // Server Second pass. Inputs hashed client id, random Y, -(x+y)*SEC, xID and xCID and Server secret SST. E and F help kangaroos to find error. 
  // If PIN error not required, set E and F = NULL 
		rtn=ctx.MPIN256.SERVER_2(date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF);
    
		if (rtn != 0)
			mywindow.document.write("FAILURE: SERVER_2 rtn: " + rtn+ "<br>");  
    
	}
    		  

	if (rtn == ctx.MPIN256.BAD_PIN)
	{
		mywindow.document.write("Server says - Bad Pin. I don't know you. Feck off." + "<br>"); 
		if (PINERROR)
		{
			var err=ctx.MPIN256.KANGAROO(E,F);
			if (err!=0) mywindow.document.write("(Client PIN is out by "+err + ")<br>");
		}
	}
	else 
	{
		mywindow.document.write("Server says - PIN is good! You really are "+IDstr + "<br>"); 
		if (FULL)
		{
			H=ctx.MPIN256.HASH_ALL(sha,HCID,pxID,pxCID,SEC,Y,Z,T);
			ctx.MPIN256.CLIENT_KEY(sha,G1,G2,pin,R,X,H,T,CK);
			
			mywindow.document.write("Client Key =  0x"+ctx.MPIN256.bytestostring(CK) + "<br>");    
			H=ctx.MPIN256.HASH_ALL(sha,HSID,pxID,pxCID,SEC,Y,Z,T);
			ctx.MPIN256.SERVER_KEY(sha,Z,SST,W,H,pHID,pxID,pxCID,SK);
			mywindow.document.write("Server Key =  0x"+ctx.MPIN256.bytestostring(SK) + "<br>");    
		}
	}

}


//bls48();
//bls24();
//bls383();
//bn254();
//goldilocks();
//nist256();
//ed25519();
//rsa2048();

</script>
</body>
</html>
